home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tech Arsenal 1
/
Tech Arsenal (Arsenal Computer).ISO
/
tek-02
/
boi120p.zip
/
UNITS.ZIP
/
ASYNC.PAS
next >
Wrap
Pascal/Delphi Source File
|
1990-12-09
|
7KB
|
194 lines
{$D-} { Debug Information Off }
{$S-} { Stack Checking Off }
{$V-} { String Checking Off }
Unit Async;
{ Part of BBS Onliner Interface }
{ Copyright (C) 1990 Andrew J. Mead
All Rights Reserved. }
{ original version 9/5/90
history found in IOLIB.PAS }
INTERFACE
Function CARRIER : boolean; { Carrier Detect function }
Procedure DROPCARRIER; { Drop Carrier }
Procedure ASYNCINT; Interrupt; { Comport Interrupt Routine }
Procedure SENDCHAR(outchar : char); { Comport Output Routine }
Function CHARREADY : boolean; { Character Ready for Input }
Function READBUFFER : char; { Get Character from buffer }
Procedure CLEARINBUFFER; { Empty input buffer }
Procedure SETBUFFERSIZE(newsize : integer); { Set buffer size, defaul = 1k }
Procedure INTINIT; { Install Comport Interrupt }
Procedure INTEND; { Disable Comport Interrupt }
IMPLEMENTATION
Uses
boidecl,
iolib,
dos;
Const
null = #0;
maxbuffsize = 1024;
THRoff = $00; { 8250 UART Transmitter Holding Register offset }
RBRoff = $00; { 8250 UART Receiver Buffer Register offset }
DLLoff = $00; { 8250 UART Divisor Latch Least Significant Byte offset }
DLMoff = $01; { 8250 UART Divisor Latch Most Significant Byte offset }
IERoff = $01; { 8250 UART Interrupt Enable Register offset }
IIRoff = $02; { 8250 UART Interrupt Identification Register offset }
LCRoff = $03; { 8250 UART Line Control Register offset }
MCRoff = $04; { 8250 UART Modem Control Register offset }
LSRoff = $05; { 8250 UART Line Status Register offset }
MSRoff = $06; { 8250 UART Modem Status Register offset }
PICCMD = $20; { 8259A Programmable Interrupt Controller Port }
PICMSK = $21; { 8259A Programmable Interrupt Controller Port }
RTSbit = $20; { Ready To Send bit in LSR }
CTSbit = $10; { Clear To Send bit in MSR }
DCDbit = $80; { Data Carrier Detect (RLSD) bit in MSR }
DCval = $08; { changes carrier detect bit in MSR }
DTRhigh = $00; { force DTR high value }
Type
portbufftype = array [1..maxbuffsize] of char;
Var
portbuffer : portbufftype; { Circular input buffer }
bufflimit : integer; { Current maximum buffer size }
buffsize : integer; { Number of character in buffer }
buffend : integer; { Index pointing to last character in buffer }
buffstart : integer; { Index pointing to first character in buffer }
asyncvector : pointer; { original interrupt vector }
IIRstatus : byte; { 8250 UART IIR status byte }
LSRstatus : byte; { 8250 UART LCR status byte }
Function CARRIER : boolean;
{ This function will return 'true' if a carrier is present.}
begin {* fCarrier *}
Carrier := dolocal or (not checkcd) or
((port[portadd + MSRoff] and DCDbit) = DCDbit)
end; {* fCarrier *}
Procedure DROPCARRIER;
{ This function will force the modem to hang up the phone.}
var
timebase : longint;
begin {* DropCarrier *}
TimerSet(timebase);
repeat port[portadd + MCRoff] := DTRhigh
until GetTimer(timebase,2)
end; {* DropCarrier *}
Procedure ASYNCINT;
begin {* AsyncInt *}
inline($FB); { STI }
IIRstatus := port[portadd + IIRoff]; { read IIR status }
if ((IIRstatus and $06) = $04) then { check to see if character waiting }
begin { place character in buffer }
if buffsize < bufflimit then
begin
portbuffer[buffend] := Char(Port[portadd + RBRoff]);
if buffend < bufflimit then Inc(buffend) else buffend := 1;
Inc(buffsize)
end
else LSRstatus := Port[portadd + RBRoff] { clear LSR status byte }
end
else if ((IIRstatus and $06) = $06) then LSRstatus := Port[portadd + RBRoff];
inline($FA); { CLI }
port[PICCMD] := $20 { reset 8259A PIC }
end; {* AsyncInt *}
Procedure SENDCHAR(outchar : char);
var
timecnt : word;
timebase : longint;
begin {* SendChar *}
TimerSet(timebase);
timecnt := 0;
while (port[portadd + LSRoff] and RTSbit <> RTSbit) or { UART ready }
(baudlock and (port[portadd + MSRoff] and CTSbit <> CTSbit)) do
begin { ^^ modem ready }
Inc(timecnt);
if not Carrier then DoTimeOut(false)
else if timecnt mod 1000 = 0 then if GetTimer(timebase,60) then DoTimeOut(false)
end;
port[portadd + RBRoff] := ord(outchar) { send character }
end; {* SendChar *}
Function CHARREADY : boolean;
begin {* fCharReady *}
CharReady := buffsize > 0
end; {* fCharReady *}
Function READBUFFER : char;
var
rb : char;
begin {* fReadBuffer *}
if CharReady then
begin
rb := portbuffer[buffstart];
if buffstart < bufflimit then Inc(buffstart) else buffstart := 1;
Dec(buffsize);
ReadBuffer := rb
end
else ReadBuffer := null
end; {* fReadBuffer *}
Procedure CLEARINBUFFER;
begin {* ClearInBuffer *}
buffend := buffstart;
buffsize := 0
end; {* ClearInBuffer *}
Procedure SETBUFFERSIZE(newsize : integer);
begin {* SetBufferSize *}
if (newsize > 1) and (newsize <= maxbuffsize) then
begin
buffstart := 1;
ClearInBuffer;
bufflimit := newsize
end;
end; {* SetBufferSize *}
Procedure INTINIT;
var
inittemp : byte;
begin {* IntInit *}
fillchar(portbuffer,sizeof(portbuffer),32);
buffend := 1;
buffstart := 1;
buffsize := 0;
bufflimit := maxbuffsize;
GetIntVec(portint,asyncvector); { save old interrupt vector }
SetIntVec(portint,@AsyncInt); { install AsyncInt vector }
Port[PICMSK] := Port[PICMSK] and initval; { access 8259A PIC }
Port[portadd + LCRoff] := Port[portadd + LCRoff] and $7F;
{ disable divisor latch register }
Port[portadd + IERoff] := $01; { enable interrupts }
Port[portadd + MCRoff] := $0B; { set RTS, DTR and OUT2 }
{ Port[portadd + MSRoff] := $80; }
inittemp := Port[portadd + LSRoff]; { reset LSR }
Port[PICCMD] := $20 { reset 8259A PIC }
end; {* IntInit *}
Procedure INTEND;
begin {* IntEnd *}
SetIntVec(portint,asyncvector); { re-install old interrupt vector }
Port[PICCMD] := $20 { reset 8259A PIC }
end; {* IntEnd *}
end. Unit